package ru.kradef.taxi.service;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;

public class HttpsServer {
    public static final String CONTENT_LENGTH = "Content-length";
    public static final String CONTENT_TYPE = "Content-type";

    private static final String EOL = "\r\n";
    private static final String JKS = "JKS";
    private static final String SC_NO_CONTENT = "HTTP/1.1 200 OK" + EOL + "Content-Type: text/plain" + EOL
	    + "Cache-Control: private" + EOL + EOL;

    private InetSocketAddress bindAddress;
    private ServerSocket serverSocket;

    public HttpsServer(InetSocketAddress bindAddress) {
	this.bindAddress = bindAddress;
    }

    public void accept(HttpRequestHandler handler) throws IOException {
	if (serverSocket == null) {
	    throw new IllegalStateException("Server was not initialized");
	}
	SSLSocket socket = (SSLSocket) serverSocket.accept();

	InputStream inputStream = socket.getInputStream();
	HttpRequest request = readRequest(inputStream);
	System.out.println(request);
	handler.service(request, new HttpResponse(socket));

	socket.close();
    }

    private HttpRequest readRequest(InputStream inputStream) throws IOException {
	BufferedInputStream is = new BufferedInputStream(inputStream);
	byte[] buf = new byte[1024];
	ByteArrayOutputStream buffer = new ByteArrayOutputStream();
	int read = 0;
	while ((read = is.read(buf)) > 0) {
	    System.out.println(read);
	    buffer.write(buf, 0, read);
	    String string = buffer.toString();
	    if (string.endsWith(EOL + EOL)) {
		break;
	    }
	}
	String request = buffer.toString();
	System.out.println(request);
	return new HttpRequest(request);
    }

    /*
     * $ keytool -genkey -alias alias -keypass simulator \ -keystore
     * lig.keystore -storepass simulator
     */
    public void init(String keyStoreFileName, char[] keyStorePassword, char[] keyRecoveryPassword)
	    throws GeneralSecurityException, IOException {
	// initialize the key store
	KeyStore ks = KeyStore.getInstance(JKS);
	ks.load(new FileInputStream(keyStoreFileName), keyStorePassword);
	// setup the key manager factory
	KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
	kmf.init(ks, keyRecoveryPassword);
	// setup the HTTPS context and parameters
	SSLContext sslContext = SSLContext.getInstance("SSLv3");
	sslContext.init(kmf.getKeyManagers(), null, null);
	init(sslContext);
    }

    public void init(SSLContext sslContext) throws IOException {
	SSLServerSocketFactory ssf = sslContext.getServerSocketFactory();
	serverSocket = ssf.createServerSocket(bindAddress.getPort(), 0, bindAddress.getAddress());
    }

    public void close() {
	try {
	    serverSocket.close();
	} catch (IOException e) {
	    // silent close
	}
    }

}
